/**
 *  jQuery.jsonengine.utils
 */
(function($) {
	$.jsonengine.utils = function(){};
	$.jsonengine.utils.version = '03-09-2011';
	/**
	 * htmlタグをエスケープします
	 */
	$.jsonengine.utils.escapetag = function(o) {
		if (Object.prototype.toString.call(o) !== '[object String]') return o;
		return o.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
	};
	/**
	 * urlからパラメーターを取得する
	 */
	$.jsonengine.utils.getParameter = function(url){
		if (url.match(/https?[^?]+\?([^#]*)/)) {
			var q = RegExp.$1;
			var a = q.split('&')
			var parameter = [];
			for (var n in a) {
				if (a[n].match(/^([^=]+)=(.*)$/)) {
					parameter[RegExp.$1] = decodeURIComponent(RegExp.$2);
				}
			}
			return parameter;
		}
		return [];
	};
	/**
	 * prettyURL
	 */
	$.jsonengine.utils.prettyURL = function(url){
		url = unescape(url);
		if (url.match(/https?[^?]+\#!(.*)/)) {
			return RegExp.$1;
		}
		return;
	};
})(jQuery);

/**
 *  jQuery.jsonengine.fn
 */
(function($) {
	$.jsonengine.fn = function(){};
	$.jsonengine.fn.version = '03-05-2011';
	/**
	 * htmlに記述された情報からdocType文字列を構築する
	 */
	$.jsonengine.fn.docType = function(o) {
		try {
			return $(o)
				.attr('class')
				.match(/_je_.*?\b/)[0]
				.replace('_je_','');
		} catch(e) {
			return;
		}
	};
	/**
	 * htmlに記述された情報からURL文字列を構築する
	 */
	$.jsonengine.fn.url = function(o) {
		var d = this.docType(o);
		if(!d) return;
		return '/_je/' + d + $(o)
			.find('.query').eq(0)
			.text()
			.trim();
	};
	/**
	 * プラグインで使用するデフォルトの成功処理関数を返す
	 */
	$.jsonengine.fn.success = function(o){
		switch (o.type) {
			case 'GET':
				if (o.object.jquery) {
					return $.jsonengine.fn.basic.success_LOAD;
				} else {
					return $.jsonengine.fn.basic.success_GET;
				}
			case 'POST':
				return $.jsonengine.fn.basic.success_POST;
			case 'PUT':
				return $.jsonengine.fn.basic.success_PUT;
			case 'DELETE':
				return $.jsonengine.fn.basic.success_DELETE;
			default :
				break;
		}
		return;
	};
	/**
	 * プラグインで使用するデフォルトの成功処理関数を返す
	 */
	$.jsonengine.fn.error = function(o){
		switch (o.type) {
			case 'GET':
				if (o.object.jquery) {
					return $.jsonengine.fn.basic.error_LOAD;
				} else {
					return $.jsonengine.fn.basic.error_GET;
				}
			case 'POST':
				return $.jsonengine.fn.basic.error_POST;
			case 'PUT':
				return $.jsonengine.fn.basic.error_PUT;
			case 'DELETE':
				return $.jsonengine.fn.basic.error_DELETE;
			default :
				break;
		}
		return;
	};
	/**
	 * jsonengineプラグイン定義のベース関数
	 */
	$.jsonengine.fn.base = function(o){
		if(o.success){
			o.success = o.success;
		}else{
			o.success = this.success(o);
		}
		if(o.error){
			o.error = o.error;
		}else{
			o.error = this.error(o);
		}
		o.success = (o.success)? o.success : this.success(o);
		o.error   = (o.error)? o.error : this.error(o);
		// o にデータ表示領域のjQueryオブジェクトが渡された場合
		if (o.object.jquery) {
			o.url = $.jsonengine.fn.url(o.object);
		}
		// o にformエレメントが渡された場合
		else {
			if (o.type === 'GET' || o.type === 'DELETE') {
				o.url = $.jsonengine.fn.url(o.object) + '/' + o.data._docId;
				o.data = '';
			} else {
				o.url = $.jsonengine.fn.url(o.object);
			}
		}
		if (!o.url) return;
		$.jsonengine.ajax({
			"type"    : o.type,
			"url"     : o.url,
			"data"    : o.data,
			"success" : $.jsonengine.success(o.object, o.success),
			"error"   : $.jsonengine.error(o.object, o.error)
		});
	};
})(jQuery);

/**
 *  jQuery.jsonengine plugin
 */
(function($) {
	// プラグインの定義
	$.fn.extend( {
		/**
		 * jsonengineから取得したjsonをhtmlリストへ変換し表示用要素内に追加するプラグイン
		 */
		_LOAD : function(s, e) {
			for(var i=0; i < this.length; i++){
				var o = {
					"object" :this.eq(i),
					"type"   :"GET",
					"data"   :"",
					"success":s,
					"error"  :e
				};
				$.jsonengine.fn.base(o);
			}
			return this;
		},
		/**
		 * フォームに入力されたデータを元にjsonengineへ問い合わせ、フォームに読み込むプラグイン
		 * 問い合わせは_docIdを用いる
		 */
		_GET : function(s, e) {
			var o = {
				"object" :this.get(0).form,
				"type"   :"GET",
				"success":s,
				"error"  :e
			};
			o.data = $(o.object).values();
			$.jsonengine.fn.base(o);
			return this;
		},
		/**
		 * フォームに入力されたデータをjsonengineへ登録するプラグイン
		 */
		_POST : function(s, e) {
			var o = {
				"object" :this.get(0).form,
				"type"   :"POST",
				"success":s,
				"error"  :e
			};
			o.data = $(o.object).values();
			//BUG jquery.valuesのバグ。textareaにnullが入ってしまう際の対応。
			var textarea = $('textarea', o.object);
			for (var i=0; i < textarea.length; i++) {
				if (textarea.eq(i).val() === '') {
					o.data[textarea.eq(i).attr('name')] = '';
				}
			}
			//BUG ここまで
			if (o.data._docId === '') delete o.data._docId;
			$.jsonengine.fn.base(o);
			return this;
		},
		/**
		 * フォームに入力されたデータをjsonengineへ更新するプラグイン
		 */
		_PUT : function(s, e) {
			var o = {
				"object" :this.get(0).form,
				"type"   :"PUT",
				"success":s,
				"error"  :e
			};
			o.data = $(o.object).values();
			//BUG jquery.valuesのバグ。textareaにnullが入ってしまう際の対応。
			var textarea = $('textarea', o.object);
			for (i=0; i < textarea.length; i++) {
				if (textarea.eq(i).val() === '') {
					o.data[textarea.eq(i).attr('name')] = '';
				}
			}
			//BUG ここまで
			$.jsonengine.fn.base(o);
			return this;
		},
		/**
		 * フォームに入力されたデータを元にjsonengineへ問い合わせ、フォームに読み込むプラグイン
		 */
		_DELETE : function(s, e) {
			var o = {
				"object" :this.get(0).form,
				"type"   :"DELETE",
				"success":s,
				"error"  :e
			};
			o.data = $(o.object).values();
			$.jsonengine.fn.base(o);
			return this;
		},
		/**
		 * フォームに入力されたデータを元にjsonengineへ問い合わせ、表示領域に読み込むプラグイン
		 * 問い合わせはシステムのパラメータ以外の入力データで構築する
		 */
		_SEARCH : function(s, e) {
			var values = $(this.get(0).form).values();
			//BUG jquery.valuesのバグ。textareaにnullが入ってしまう際の対応。
			var textarea = $('textarea', this.get(0).form);
			for (var i=0; i < textarea.length; i++) {
				if (textarea.eq(i).val() === '') {
					values[textarea.eq(i).attr('name')] = '';
				}
			}
			//BUG ここまで
			delete values._docId;
			delete values._createdAt;
			delete values._updatedAt;
			delete values._displayName;
//issule	delete values._createdBy; これは_displayNameに変わった？
			var docType = $.jsonengine.fn.docType(this.get(0).form);
			var elements = $('*:[class^=_je_' + docType + ']:not(form:[class^=_je_])');
			for (i = 0; i < elements.length; i++) {
				var el_query = $('.query', elements.eq(i));
				var tmp = el_query.text();
				var query = '';
				for (var k in values) {
					//issule 配列を検索する手段がない？
					if (Object.prototype.toString.call(values[k]) !== '[object Array]') {
						if (values[k] !== '' && values[k] !== null) {
							query += '&cond=' + k + '.eq.' + values[k];
						}
					}
				}
				query = (query!=='')? '?' + query.substr(1, query.length) : tmp;
				el_query.text(query);
				var object = {
					"object" :elements.eq(i),
					"type"   :"GET",
					"data"   :"",
					"success":s,
					"error"  :e
				};
				$.jsonengine.fn.base(object);
				el_query.text(tmp);
			}
			return this;
		}
	});
})(jQuery);

/**
 *  jQuery.jsonengine.fn.basic
 */
(function($) {
	$.jsonengine.fn.basic = function(){};
	$.jsonengine.fn.basic.version = '03-09-2011';
	/**
	 * jQuery.jsonengine で用いられるアラート表示です。
	 * ユーザーが再定義する事で表示方法が変えられます。
	 */
	$.jsonengine.fn.basic.alert = function(message) {
		console.log(message);
	};
	/**
	 * jQuery.jsonengine で用いられるログイン警告表示です。
	 * ユーザーが再定義する事で表示方法が変えられます。
	 */
	$.jsonengine.fn.basic.redirectDialog = function(href) {
		$.jsonengine.fn.basic.alert('ログインして下さい');
	};
	/**
	 * jsonengineからデータ読み込み成功した際のコールバック関数
	 */
	$.jsonengine.fn.basic.success_LOAD = function(o, response, status) {
		$.jsonengine.fn.basic.alert('success LOAD');
	};
	/**
	 * jsonengineからデータ読み込み失敗した際のコールバック関数
	 */
	$.jsonengine.fn.basic.error_LOAD = function(o, xhr, status, thrown){
		$.jsonengine.fn.basic.alert('error LOAD');
	};
	/**
	 * jsonengineから1件取得が成功した際のコールバック関数
	 */
	$.jsonengine.fn.basic.success_GET = function(o, response, status) {
		$.jsonengine.fn.basic.alert('success GET');
	};
	/**
	 * jsonengineから1件取得がが失敗した際のコールバック関数
	 */
	$.jsonengine.fn.basic.error_GET= function(o, xhr, status, thrown){
		$.jsonengine.fn.basic.alert('error GET');
	};
	/**
	 * jsonengineへ新規登録が成功した際のコールバック関数
	 */
	$.jsonengine.fn.basic.success_POST = function(o, response, status) {
		$.jsonengine.fn.basic.alert('success POST');
	};
	/**
	 * jsonengineへ新規登録が失敗した際のコールバック関数
	 */
	$.jsonengine.fn.basic.error_POST = function(o, xhr, status, thrown){
		$.jsonengine.fn.basic.alert('error POST');
	};
	/**
	 * jsonengineへ更新が成功した際のコールバック関数
	 */
	$.jsonengine.fn.basic.success_PUT = function(o, response, status) {
		$.jsonengine.fn.basic.alert('success PUT');
	};
	/**
	 * jsonengineへ更新が失敗した際のコールバック関数
	 */
	$.jsonengine.fn.basic.error_PUT = function(o, xhr, status, thrown){
		$.jsonengine.fn.basic.alert('error PUT');
	};
	/**
	 * jsonengineで削除が成功した際のコールバック関数
	 */
	$.jsonengine.fn.basic.success_DELETE = function(o, response, status) {
		$.jsonengine.fn.basic.alert('success DELETE');
	};
	/**
	 * jsonengineで削除が失敗した際のコールバック関数
	 */
	$.jsonengine.fn.basic.error_DELETE = function(o, xhr, status, thrown){
		$.jsonengine.fn.basic.alert('error DELETE');
	};
})(jQuery);

/**
 * jQuery.jsonengine bind event.
 */
$(function() {
	//prettyURLが存在していればデータを取得しセットする
	var docId = $.jsonengine.utils.prettyURL(location.href);
	if (docId) {
		var form = $('form[class^=_je_]:not(form.search, form.noset)');
		for (var i=0; i < form.length; i++) {
			$(':text[name="_docId"]',form.eq(i)).val(docId)._GET();
		}
		var view = $('*:[class^=_je_]:not(form:[class^=_je_], input:[class^=_je_], select:[class^=_je_]), textarea:[class^=_je_], button:[class^=_je_]');
		for (var i=0; i < view.length; i++) {
			var query = view.eq(i).children('.query');
			if (query.text() === '_docId') {
				query.text('/' + docId);
			}
		}
	}

	//データ表示
	var tmpView = $('*:[class^=_je_]:not(form:[class^=_je_], input:[class^=_je_], select:[class^=_je_]), textarea:[class^=_je_], button:[class^=_je_]');
	var emptyView=[], view=[], c=0;
	for(var i=0; i<tmpView.length; i++) {
		if($(tmpView[i]).find('.query').text() === '_docId'){
			emptyView[c++] = tmpView[i];
		} else {
			view[c++] = tmpView[i];
		}
	}
	for(var i=0; i<emptyView.length; i++) {
		$(emptyView[i])
			.append($($('<p>').append($('.template', emptyView[i]).clone()).html().replace(/{{(.+?)}}/g, '')).attr('class','result'))
			.find('.query,.template')
			.css('display','none');
	}
	$(view)._LOAD();

	//イベント割り当て　コマンドボタン
	$('form[class^=_je_]:not(form.search, form.noset)').find('._GET').click(function(){
		$(this)._GET();
	});
	$('form[class^=_je_]:not(form.search)').find('._POST').click(function(){
		$(this)._POST();
	});
	$('form[class^=_je_]:not(form.search)').find('._PUT').click(function(){
		$(this)._PUT();
	});
	$('form[class^=_je_]:not(form.search)').find('._DELETE').click(function(){
		$(this)._DELETE();
	});
	$('form[class^=_je_]').find('._SEARCH').click(function(){
		$(this)._SEARCH();
	});

	//イベント割り当て　リロード
	$('*[class^=#_je_]').click(function(){
		$($(this).attr('class').match((/#_je_.*?\b/))[0])._LOAD();
	});

	//submitをキャンセル
	$('form').submit(function(){
		return false;
	});

});

